#! /usr/bin/python

# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__ = "furoscame"
__date__ = "29.12.11 23:28"
debug = False

import subprocess
import threading
import time

import chessprogram_config
import mosal_a
from mosal_message import MosalMessage
import wb_processor

class ChessprogramAdapter:
    """
    Documentation
    """
    def __init__(self, osa_control):
        #self.osa_control = OSAControl()
        self.mosal = mosal_a.MosalA()
        self.osa_control = osa_control
        cp_config = chessprogram_config.ChessprogramConfig()
        #cp_config.set_delphi()
        #cp_config.set_comet()
        #open chessprogram
        if debug:
            print (cp_config.path_to_program, cp_config.program)
        self.move_count = 0
        self.cp = subprocess.Popen(cp_config.path_to_program + cp_config.program, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
                                   shell=False, cwd=cp_config.path_to_program)
        if cp_config.protocol == "WB1":
            print ("Currently not supported!")
            pass
        elif cp_config.protocol == "WB1_Edit":
            pass
        elif cp_config.protocol == "WB2":

            if debug:
                print ("WB2 found!")

            self.processor = wb_processor.WB2Processor()
            self.program_state = 'not'

        else:
            print ("Unknown Protocol!")

        self.mosal_message_hint = MosalMessage('InfoArea')
        self.mosal_message_hint.set('ready', False)
        self.mosal_message_hint.set('move', 'False')
        if debug:
            print (self.mosal_message_hint.print_message())
        self.block_move = False
        self.move_sent = True
        self.move_to_send = ""
        self.state = "Wait"
        self.suppress_hint = True
        self._level_sync = False
        self._pos_sync = False
        self.sync = False
        pass
    pass

    def shortcut(self):
        """
        Go reading the the program via stdin/stdout
        """
        self.alive = True
        self.thread_read = threading.Thread(target=self.reader)
        self.thread_read.setDaemon(True)
        self.thread_read.setName('CP->Adapter')
        self.thread_read.start()
        pass
    pass

    def reader(self):
        while self.alive:
            data = self.cp.stdout.readline()
            print ("from chessprogram: ", data)
            self.process_engine_message(data)
        pass
    pass

    def process_engine_message(self, message):
        ret = self.processor.parse_engine_message(message)
        if debug:
            print ("ret :", ret)
        if ret[0] == 'ready':
            print ("chessprogram is ready")
            self.program_state = 'ok'
            pass
        elif ret[0] == 'feature':
            if debug:
                print ("feature detected")
        elif ret[0] == 'move':

            print ("move", ret[1])
            self.move_to_send = ret[1]
            self.check_move_to_hint(ret[1])
            self.mosal_message_hint.set('ready', True)
            mosal_str = self.mosal.get_mosal_string(self.mosal_message_hint)
            if debug:

                print ("der Move", mosal_str)
            self.hint = mosal_str
            
            self.tell_to_leo()

#            message = mosal_a.MosalMessage('SearchFinished')
#            message.set('move', ret[1])
            self.block_move = True # Leo send this move back and confuses cp
            self.suppress_hint = True
#            self.move_in_mosal = self.mosal.get_mosal_string(message)
            
        elif ret[0] == 'hint':
            if self.suppress_hint == False:
                self.create_hint_to_hint(ret[1])
                mosal_str = self.mosal.get_mosal_string(self.mosal_message_hint)
                if debug:
                    print (mosal_str)
                self.osa_control.tell_to_leo(mosal_str)
            else:
                if debug:
                    print ('hint suppressed!')
        elif ret[0] == 'resign':
            #mosal_message = MosalMessage('AbortSearch')
            if debug:
                print ("res:", self.mosal_message_hint.get('score'))
            if self.mosal_message_hint.get('score') > 0x8000:
                self.mosal_message_hint.set('score', 0xFFFF)
            else:
                self.mosal_message_hint.set('score', 0x0001)
                
            self.mosal_message_hint.set('ready', True)
            mosal_str = self.mosal.get_mosal_string(self.mosal_message_hint)
            print ('resign', mosal_str)
            self.tell_to_leo()
            pass
    pass

    def resend_move(self):
        if self.state == "Move":
            print ("Resend:", self.hint)
            self.osa_control.tell_to_leo(self.hint)
        pass

    def check_move_to_hint(self, move):
        if self.mosal_message_hint.get('move') != move:   #   pv displayable/ searched enough
            self.mosal_message_hint.set('DMFLGS', 0x80)  #  '1100 0000
            self.mosal_message_hint.set('score', 0x0F00) # equal because of book move
            self.mosal_message_hint.set('depth', 0)
            self.mosal_message_hint.set('val_led', 4)
            self.mosal_message_hint.set('move', move)
            main_var = []
            main_var.append(move)
            self.mosal_message_hint.set('main_var', main_var)

            pass
        pass
        #self.mosal_message_hint.DMFLGS = 0xC0
        
    pass

    def create_hint_to_hint(self, hint):

        """

:param hint:
"""
        print ("move count",self.move_count)
        if (self.processor.get_processor_type() == "WB2") and ((self.move_count % 2) == 1):
            hint.score = -1 * hint.score

        self.mosal_message_hint.set('DMFLGS', 0x80)  #  '1010 0000

        if hint.score > 9800:
            self.mosal_message_hint.set('score', 0xFFFF -  (9999 - hint.score))
        elif hint.score < -9800:
            self.mosal_message_hint.set('score', 0x0001 +  (9999 + hint.score))
        elif hint.score == 0:
            self.mosal_message_hint.set('score', 0x8000)
        else:
            self.mosal_message_hint.set('score', 0x8000 + ((hint.score * 16)  / 10))
        
        self.mosal_message_hint.set('depth', hint.depth)
        if debug:
            print (("Score ---", hint.score))
        if hint.score > 700:
            self.mosal_message_hint.set('val_led', 0)
            print ((0))
            pass
        elif  hint.score > 500:
            self.mosal_message_hint.set('val_led', 1)
            print (1)
            pass
        elif hint.score > 175:
            self.mosal_message_hint.set('val_led', 2)
            print (2)
            pass
        elif hint.score > 75:
            self.mosal_message_hint.set('val_led', 3)
            print (3)
            pass
        elif hint.score > -75:
            self.mosal_message_hint.set('val_led', 4)
            print (4)
            pass
        elif hint.score > -175:
            self.mosal_message_hint.set('val_led', 5)
            print (5)
            pass
        elif hint.score > -500:
            self.mosal_message_hint.set('val_led', 6)
            print (6)
            pass
        else:
            self.mosal_message_hint.set('val_led', 7)
            print (7)
            pass

        if len(hint.pvariante) > 0:
            self.mosal_message_hint.set('move', hint.pvariante[0])

        if debug:
            print ("Move", self.mosal_message_hint.get('move'))
        self.mosal_message_hint.set('main_var', [])
        
        for move in hint.pvariante:
            self.mosal_message_hint.get('main_var').append(move)
    
    pass

    def calc_score_to_leo_format(self):
        pass
    pass

    def start_program(self):
        self.program_state = 'start'
        self.shortcut()
        cmd = self.processor.get_start_cmd()
        self.cp.stdin.write(cmd)
        pass
    pass

    def is_running(self):
        return self.program_state
    pass

    def synchronize(self):
        pass
    pass

    def _tell_to_engine(self, message):
        if self.sync == False:
            print ("tell to engine in snyc")
            if debug:
                print (message.print_message())
            cp_cmd = self.processor.parse_message(message)
            if debug:
                print ("chessprogram commands", cp_cmd)

            if message.message == "Setlevel":
                self._level_sync = True
            if message.message == "Position":
                self._pos_sync = True


            for cmd in cp_cmd:
                print ("to send", cmd)
                self.cp.stdin.write(cmd + "\n")
            pass

            self.sync = self._level_sync and self._pos_sync
            print ("SYNC", self.sync, self._level_sync, self._pos_sync)
        else:
            if message.message == "MoveRecognized":
                print ("Leo Move to CP", message.get('move'))
                self.cp.stdin.write(message.get('move') + "\n")
            elif message.message == "MoveMade":
                if self.block_move == False:
                    self.suppress_hint = False
                    print ("Leo Move to CP", message.get('move'))
                    self.cp.stdin.write(message.get('move') + "\n")
                else:
                    self.block_move = False
            else:
                cp_cmd = self.processor.parse_message(message)
                for cmd in cp_cmd:
                    print ("to send", cmd)
                    self.cp.stdin.write(cmd + "\n")
            pass
        pass
    pass

    def tell_to_engine(self, message):
        if self.sync == False:
            print ("tell to engine in snyc")
            if debug:
                print (message.print_message())
            cp_cmd = self.processor.parse_message(message)
            if debug:
                print ("chessprogram commands", cp_cmd)

            if message.message == "Setlevel":
                self._level_sync = True
            if message.message == "Position":
                self._pos_sync = True


            for cmd in cp_cmd:
                print ("to chessprogramm: ", cmd)
                self.cp.stdin.write(cmd + "\n")
            pass

            self.sync = self._level_sync and self._pos_sync
            if debug:
                print ("SYNC", self.sync, self._level_sync, self._pos_sync)

        else:
            print (message.message, self.state, self.mosal_message_hint.get('ready'), self.move_sent)
            if message.message == "BeginSearch":
                if self.state == "Wait":
                    if message.has_data('move'):
                        move = message.get('move')
                    else:
                        move = ""
                        
                    print ("GO!!", move)
                    self.state = "Calc_A"
                    #self.cp.stdin.write(message.move + "\n")
                    self.cp.stdin.write(self.processor.get_go_cmd())
                    self.suppress_hint = False

                elif self.state == "Move":
                    if self.mosal_message_hint.get('ready') == True:
                        self.mosal_message_hint.set('DMFLGS', 0xC0)
                        self.hint = self.mosal.get_mosal_string(self.mosal_message_hint)
                        self.osa_control.tell_to_leo(self.hint)
                        #self.state = "Ponder"
                    elif self.move_sent == False:
                        self.osa_control.tell_to_leo(self.hint)
                        pass
                    else:
                        print ("do a resend")
                        self.osa_control.tell_to_leo(self.hint)
                    #self.state = "Calc"
                    pass
                elif self.state == "Ponder":
                    print (self.state)
                    self.state = "Calc_A"
                    self.mosal_message_hint.set('ready', False)
                    self.cp.stdin.write(self.processor.get_go_cmd())
                    self.suppress_hint = False
                elif self.state == "Calc_N":
                    self.tell_to_leo()
                else:
                    print ("Not in Wait and got", message.print_message(), self.state)
            elif message.message == "InterruptSearch":

                if self.state == "Calc_N" or self.state == "Calc_A":

                    self.cp.stdin.write(self.processor.get_interrupt_cmd())
                    #self.check_move_to_hint(self.mosal_message_hint.move)
                    self.tell_to_leo()
                    #eifentlich finied search
                    #self.state = "Move"
                    pass
                elif self.state == "Wait":
                    self.state = "Calc_A"
                    self.cp.stdin.write(self.processor.get_go_cmd())
                    time.sleep(2)
                    self.cp.stdin.write(self.processor.get_interrupt_cmd())
                pass
            elif message.message == "FinishSearch":
                # dont know
                pass
            elif message.message == "AbortSearch":
                if self.state == "Calc_N":

                    self.state = "Wait"
                    self.cp.stdin.write(self.processor.get_stop_cmd())
                    # force mode
                pass
            elif message.message == "MoveMade":
                self.move_count = message.get('movecount')
                if debug:
                    print (self.state)
                    print ("mess move", message.get('move'), self.move_to_send)
                if self.state == "Move":
                    print ("mess move", message.get('move'), self.move_to_send)
                    if message.get('move') == self.move_to_send:
                        self.move_sent = True
                        pass
                    print ("Ok now send:", self.hint)
                    time.sleep(1)
                    self.osa_control.tell_to_leo(self.hint)
                    #self.state = "Ponder"
                    time.sleep(1)
                elif self.state == "Calc_N" or self.state == "Calc_A":
                    self.suppress_hint = False
                    self.tell_to_leo()
                    pass
                pass
            elif message.message == "MoveRecognized":

                self.move_count = message.get('movecount')
                print (self.state, self.move_count)
                if self.state == "Wait":
                    self.state = "Calc_N"
                    
                    self.mosal_message_hint.set('ready', False)
                    print ("Leo Move to CP", message.get('move'))
                    self.cp.stdin.write(message.get('move') + "\n")
                elif self.state == "Ponder":
                    self.state = "Calc_N"
                    
                    self.mosal_message_hint.set('ready', False)
                    print ("Leo Move to CP", message.get('move'))
                    self.cp.stdin.write(message.get('move') + "\n")
                elif self.state == "Move":
                    self.state = "Ponder"

                pass

            else:
                cp_cmd = self.processor.parse_message(message)
                for cmd in cp_cmd:
                    print ("to send", cmd)
                    self.cp.stdin.write(cmd + "\n")
                    if cmd == "new\n":
                        print ("new erkannt!")
                        self.state = "Wait"
                pass
            pass
        pass
    pass

    def is_open(self):
        return True
    pass

    def tell_to_leo(self):
        print ("tell_to_leo:", self.state, self.mosal_message_hint.get('ready'))
        if self.move_sent == True:
            self.move_sent == False
            if self.state == "Calc_A":
                if self.mosal_message_hint.get('ready') == True:
                    self.mosal_message_hint.set('DMFLGS', 0xC0)
                    mosal_str = self.mosal.get_mosal_string(self.mosal_message_hint)
                    self.hint = mosal_str
                    self.osa_control.tell_to_leo(self.hint)
                    self.state = "Move"
                    self.suppress_hint = True
                    self.mosal_message_hint.set('ready', False)
            elif self.state == "Calc_N":
                print ("ready", self.mosal_message_hint.get('ready'))
                if self.mosal_message_hint.get('ready') == True:
                    self.mosal_message_hint.set('DMFLGS', 0xC0)
                    mosal_str = self.mosal.get_mosal_string(self.mosal_message_hint)
                    self.hint = mosal_str
                    print ("mosal_str", mosal_str)
                    self.osa_control.tell_to_leo(mosal_str)
                    self.state = "Move"
                    self.suppress_hint = True
                    self.mosal_message_hint.set('ready', False)
            else:
                self.osa_control.tell_to_leo(self.hint)
                print ("Nothing allowed", self.state, self.hint)

    pass

    def go(self):
        print ("Go:")
        self.cp.stdin.write("go\n")
        #self.cp.stdin.flush()
    pass

    def terminate(self):
        # the universal quit command
        self.cp.stdin.write("quit")
        pass
    pass

pass

